#pragma once

#include "SimpleList.hpp"

class SimpleString
{
public:
	SimpleString() : m_chars(nullptr), m_length(0)
	{
		m_chars = new TCHAR[1];
		SecureZeroMemory(m_chars, sizeof(TCHAR));
	}

	SimpleString(const TCHAR *psz) : m_chars(nullptr), m_length(0)
	{
		size_t cchLength = _tcsnlen(psz, MAXINT - 1);
				
		m_chars = new TCHAR[cchLength + 1];
		SecureZeroMemory(m_chars, (cchLength + 1) * sizeof(TCHAR));

		if (cchLength > 0)
		{
			_tcscpy_s(m_chars, cchLength + 1, psz);
		}		
		m_length = (int) cchLength;
	}
	
	int GetLength()
	{
		return m_length;
	}
	__declspec(property(get = GetLength)) int Length;
	
	void SetLength(int length)
	{
		TCHAR *tmp;
		tmp = new TCHAR[length + 1];
		SecureZeroMemory(tmp, (length + 1) * sizeof(TCHAR));

		_tcsncpy_s(tmp, length + 1, m_chars, m_length);
		delete[] m_chars;

		m_chars = tmp;
		m_length = length;
	}

	void Append(TCHAR tchr)
	{
		SetLength(m_length + 1);
		m_chars[m_length - 1] = tchr;
		m_chars[m_length] = _T('\0');
	}

	void Append(TCHAR *psz)
	{
		size_t cchLength = _tcsnlen(psz, MAXINT - 1);

		if (cchLength > 0)
		{
			int startIndex = m_length;
			SetLength(m_length + cchLength);
			_tcscpy_s(&m_chars[startIndex], cchLength + 1, psz);
		}
	}

	bool Contains(const SimpleString &substr)
	{
		return (NULL != StrStrI(m_chars, substr.m_chars));
	}

	SimpleList<SimpleString> &Split(TCHAR cDelimiter, bool bRemoveEmptyStrings)
	{
		LPTSTR	pString;		
		SimpleList<SimpleString> *result;
		int		nArrLen = 0;

		pString = m_chars;
		size_t nStrLen = _tcsnlen(pString, MAXINT - 1);
		
		result = new SimpleList<SimpleString>();

		for (size_t i = 0; i < nStrLen; i++)
		{
			SimpleString *tmp = new SimpleString();
			
			while (cDelimiter != *pString && i < nStrLen)
			{
				tmp->Append(*pString);
				pString++;
				i++;
			}
			
			if (tmp->m_length > 0 || !bRemoveEmptyStrings)
			{
				result->Add(*tmp);
			}
			
			pString++;
		}
		
		return (*result);
	}

	const TCHAR *ToCharArray() const
	{
		return m_chars;
	}

	static const SimpleString &Empty;

	static SimpleString &LoadFromResource(HINSTANCE hInstance, UINT resourceId)
	{
		TCHAR ptr[4];
		int count = LoadString(hInstance, resourceId, ptr, 0);
		TCHAR *szLoaded = new TCHAR[count + 1];
		LoadString(hInstance, resourceId, szLoaded, count + 1);
		SimpleString *result = new SimpleString(szLoaded);
		return (*result);
	}

	static SimpleString &Format(const TCHAR *format, ...)
	{
		TCHAR *pBuffer = nullptr;
		va_list params = nullptr;
		SimpleString *result;

		va_start(params, format);
		
		FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
			format, 0, 0, (TCHAR *) &pBuffer, 0, &params);

		va_end(params);

		result = new SimpleString(pBuffer);
		LocalFree(pBuffer);
		return (*result);
	}

	~SimpleString()
	{
		if (nullptr != m_chars)
		{
			delete[] m_chars;
			m_chars = nullptr;
			m_length = 0;
		}		
	}

private:
	TCHAR	*m_chars;
	int		m_length;
};

__declspec(selectany) const SimpleString &SimpleString::Empty = _T("");
